package org.sidora.core.util;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.TreeSet;

import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.query.Predicate;
import core.VilarsFeature;
import core.context.VilarsContext;
import java.util.logging.Level;
import org.sidora.core.Action;
import org.sidora.core.Category;
import org.sidora.core.Describer;
import org.sidora.core.Feature;
import org.sidora.core.Sector;
import org.sidora.core.Site;
import org.sidora.core.Zone;
import org.sidora.core.context.Context;
import org.sidora.core.context.Equality;
import org.sidora.core.context.Succesion;

public class VilImport {
    ObjectSet oldContexts;
    ObjectSet oldFeatures;
    Site site;
    
    public VilImport() {
        site = (Site) Site.Inventory.getList().get(0);
        //importVilContexts();
        setRelations();
    }
    
    public void setRelations(){
        // Obte els VilContexts (UEs en format vell)
        
        Db4o.configure().objectClass(VilarsContext.class).cascadeOnUpdate(true);
        Db4o.configure().objectClass(VilarsContext.class).cascadeOnActivate(true);
        
        Db4o.configure().objectClass(ArrayList.class).cascadeOnUpdate(true);
        Db4o.configure().objectClass(ArrayList.class).cascadeOnActivate(true);
        
        ObjectContainer dbold = Db4o.openFile("OldVilars.yap");
        
        oldContexts =  dbold.query(VilarsContext.class);
        
        Iterator iter = oldContexts.iterator();
        
        
//		Crea contextes per a cada UE
        int i = oldContexts.size();
        int j= 0;
        int k =i-1;
        while (j<k){
            //System.out.println(j);
            i--;
            j++;
            //Obt? una UE
            VilarsContext con =(VilarsContext) iter.next();
            
            Context nou = getContext(con.UE,getZone(con.UE));
            
            TreeSet<Context> contexts;
            Context context;
            //Equality
            if(con.iguala.trim().length()>0){
                contexts = getContexts(con.iguala);
                Iterator iter3 = contexts.iterator();
                
                while(iter3.hasNext()){
                    Context contextNou = (Context) iter3.next();
                    newEquality(nou, contextNou);
                }
            }
            
            if(con.anteriora.trim().length()>0){
                contexts = getContexts(con.anteriora);
                Iterator iter3 = contexts.iterator();
                
                while(iter3.hasNext()){
                    Context contextNou = (Context) iter3.next();
                    newAnterior(nou, contextNou);
                }
            }
            
            /*
            if (con.iguala.length()>1)nou.setEqualTo(getContexts(con.iguala));
            if (con.anteriora.length()>1)nou.setPreviousTo(getContexts(con.anteriora));
            if (con.posteriora.length()>1)nou.setNextTo(getContexts(con.posteriora));
             */
            
            System.out.println("Context "+j+" de "+k);
//            AbstractInventory.setObject(nou);
            
            
        }
        dbold.close();
    }
    
    
    
    public void setCategorys(){
        List<Describer> describers = Describer.Inventory.getList(site);
        Iterator iterDescriber = describers.iterator();
        Describer describer = null;
        
        System.out.println("Describer number: "+describers.size());
        
        if (describers.size()> 0){
            describer = (Describer)iterDescriber.next();
//            System.out.println(describer.getClass().toString());
//            System.out.println(describer.getField().toString());
//            System.out.println(describer.getLabel().toString());
//            System.out.println(describer.getReferencedClass().toString());
//            System.out.println(describer.getSite().toString());
        }
        
        /*
        List<Category> categories = Category.Inventory.getList();
        Iterator iterCategories = categories.iterator();
         
        while (iterCategories.hasNext()){
            Category category = (Category)iterCategories.next();
            category.setType(describer);
            AbstractInventory.setObject(category);
        }
         */
        
    }
    
    public Context importContext(VilarsContext con){
        //Prepara els paramtres per la UE a crear
        System.out.println("A"); ///////////////////////////////////////////////////////////////////////////////
        ParameterCollector param = new ParameterCollector();
        
        param.put("type","Old");
        
        //Aconseguim la zona coresponent
        Zone zone = getZone(con.UE);
        System.out.println("b"); ///////////////////////////////////////////////////////////////////////////////
        param.put("zone", zone);
        String nue = con.UE.trim().trim();
        Integer number = new Integer(nue.subSequence(nue.length()-3,nue.length()).toString());
        
        param.put("id", number);
        System.out.println("c"); ///////////////////////////////////////////////////////////////////////////////
        //Es crea el nou Context
        Context nou = null;
        try {
            Context.Inventory ci = new Context.Inventory();
            nou = (Context)ci.getNewObject(param);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("d"); ///////////////////////////////////////////////////////////////////////////////
        nou.setActions(getActions(con.any));
        System.out.println("e"); ///////////////////////////////////////////////////////////////////////////////
        String sect = con.sector;
        TreeSet<Sector> sectors = getSectors(con.sector, zone);
        System.out.println("f"); ///////////////////////////////////////////////////////////////////////////////
        if (!sect.equals(" ")&sect!=null){
            
            nou.getSectors().addAll(sectors);
            Iterator iter2 = sectors.iterator();
            while (iter2.hasNext()){
                Sector sector = (Sector) iter2.next();
                sector.getContexts().add(nou);
                AbstractInventory.setObject(sector);
            }
        }
        System.out.println("g"); ///////////////////////////////////////////////////////////////////////////////
        if (con.relfet.length()>1){
            Feature feature = getFeature(con.relfet,zone);
            nou.setFeature(feature);
            feature.getComposition().add(nou);
            feature.getSectors().addAll(sectors);
        }
        System.out.println("h"); ///////////////////////////////////////////////////////////////////////////////
        StringBuilder descr= new StringBuilder();
        if (con.tipus.length()>1)descr.append("Tipus:"+con.tipus+"\n");
        if (con.ident.length()>1)descr.append("Ident.:"+con.ident+"\n");
        if (con.cgeog.length()>1)descr.append("C. Geol.:"+ con.cgeog+"\n");
        if (con.color.length()>1)descr.append("Color:"+con.color+"\n");
        if (con.consist.length()>1)descr.append("Consist.:"+con.consist+"\n");
        if (con.coord.length()>1)descr.append("Coord:"+con.coord+"\n");
        
        if (con.fase.length()>1)descr.append("Fase.:"+con.fase+"\n");
        if (con.TPQ.length()>1)descr.append("TPQ:"+con.TPQ+"\n");
        if (con.TAQ.length()>1)descr.append("TAQ:"+con.TAQ+"\n");
        
        if (con.iguala.length()>1)descr.append("Igual a:"+con.iguala+"\n");
        if (con.anteriora.length()>1)descr.append("Anterior a:"+con.anteriora+"\n");
        if (con.posteriora.length()>1)descr.append("Posterior a:"+con.posteriora+"\n");
        
        if (con.plantes.length()>1)descr.append("Plantes:"+con.plantes+"\n");
        if (con.seccions.length()>1)descr.append("Seccions:"+con.seccions+"\n");
        if (con.fotog.length()>1)descr.append("Foto:"+con.fotog+"\n");
        
        nou.setDescription(descr.toString());
        
        nou.setInterpretation(con.interpretacio);
        System.out.println("i"); ///////////////////////////////////////////////////////////////////////////////
        /*
        if (con.iguala.length()>1)nou.setEqualTo(getContexts(con.iguala));
        if (con.anteriora.length()>1)nou.setPreviousTo(getContexts(con.anteriora));
        if (con.posteriora.length()>1)nou.setNextTo(getContexts(con.posteriora));
         */
        
        //zone.getContexts().add(nou);
        
        return nou;
    }
    
    private TreeSet getActions(String any) {
        if (any==null)
            return null;
        //El Assign i la campanya corresponent
        
        TreeSet actions = new TreeSet();
        
        
        StringTokenizer token= new StringTokenizer(any, ",");
        
        while(token.hasMoreTokens()){
            String str = token.nextToken();
            Action act = getAction(str.trim());
            actions.add(act);
        }
        return actions;
    }
    
    private void importVilContexts() {
        // Obte els VilContexts (UEs en format vell)
        
        Db4o.configure().objectClass(VilarsContext.class).cascadeOnUpdate(true);
        Db4o.configure().objectClass(VilarsContext.class).cascadeOnActivate(true);
        
        Db4o.configure().objectClass(ArrayList.class).cascadeOnUpdate(true);
        Db4o.configure().objectClass(ArrayList.class).cascadeOnActivate(true);
        
        ObjectContainer dbold = Db4o.openFile("OldVilars.yap");
        
        oldContexts =  dbold.query(VilarsContext.class);
        oldFeatures =  dbold.query(VilarsFeature.class);
        
        Iterator iter = oldContexts.iterator();
        
        importFeatures();
        
//		Crea contextes per a cada UE
        int i = oldContexts.size();
        int j= 0;
        int k =i-1;
        while (j<k){
            //System.out.println(j);
            i--;
            j++;
            //Obt? una UE
            VilarsContext con =(VilarsContext) iter.next();
            
            Context nou = importContext(con);
            System.out.println("Context "+j+" de "+k);
            /*
            if (con.iguala.length()>1)nou.setEqualTo(getContexts(con.iguala));
            if (con.anteriora.length()>1)nou.setPreviousTo(getContexts(con.anteriora));
            if (con.posteriora.length()>1)nou.setNextTo(getContexts(con.posteriora));
             */
            
            
            AbstractInventory.setObject(nou);
            
            
        }
        dbold.close();
    }
    
    
    private void importFeatures() {
        
        ObjectContainer db = OCProvider.getInstance();
        
        Iterator iter = oldFeatures.iterator();
        //Itera la coleccio de fets antics
        int i = oldFeatures.size();
        int j= 0;//inici
        int k = i-1;//final
        
        while (j<k){
            
            i--;
            j++;
            //Obte un feature antic
            VilarsFeature fet = (VilarsFeature) oldFeatures.get(j) ;
            Feature feature = null;
            
            //Busca la seva zona
            Zone zone = null;
            final Integer integ = new Integer(fet.zona.trim());
            
            List<Zone> list = db.query(new Predicate<Zone>(){
                public boolean match(Zone zone) {
                    return zone.getIdZone().getNumber().equals(integ);
                }
                
            });
            if (list.size()!=0)
                zone= list.iterator().next();
            
            else{
                //System.out.println("Crea una nova zona:");
                ParameterCollector param = new ParameterCollector();
                Zone.Inventory zi = new Zone.Inventory();
                
                param.put("site",site);
                
                //Zone zone = null;
                try {
                    zone = zi.getNewObject(param);
                    zone.setDescription("New Zone");
                    
                    zi.setObject(zone);
                }catch (Exception e1) {
                    LoggerProvider.getInstance().log(Level.WARNING,"Exception",e1);
                }
                
            }
            
            
            
            ParameterCollector param = new ParameterCollector();
            param.put("zone", zone);
            param.put("site", site);
            
            Category cat = getCategory(fet.tipus);
            
            param.put("type",cat);
            
            
            try {
                Feature.Inventory fi = new Feature.Inventory();
                feature = fi.getNewObject(param);
                
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Integer number = new Integer(fet.id.trim());
            feature.getIdFet().setNumber(number);
            feature.setCommentary(fet.descr+" ("+fet.fase+")");
            feature.setArchactions(getActions(fet.any));
            TreeSet <Sector> set = getSectors(fet.sector,zone);
            
            
            feature.getSectors().addAll(set);
            
            zone.getFeatures().add(feature);
            AbstractInventory.setObject(zone);
            
            System.out.println("Feature "+j+" de "+k);
        }
        
    }
    
    private Category getCategory(final String tipus) {
        ObjectContainer db = OCProvider.getInstance();
        
        //Obtenir la categoria
        Category cat = null;
        List <Category>cats = db.query(new Predicate <Category> (){
            @Override
            public boolean match(Category candidate) {
                return candidate.getLabel().equals(tipus);
            }
        });
        if (cats.size()>0) cat = cats.get(0);
        
        if (cat==null){
            System.out.println("OJO2!"+tipus);
        }
        return cat;
    }
    
    
    public Feature getFeature(String relfet, final Zone zone) {
        
        Feature feature =null;
        
        if (relfet.contains(",")|| relfet.contains("/")){
            StringTokenizer atoken =null;
            if (relfet.contains(","))  atoken = new StringTokenizer(relfet.trim(),",");
            if (relfet.contains("/"))  atoken = new StringTokenizer(relfet.trim(),"/");
            
            while (atoken.hasMoreTokens()){
                String str = atoken.nextToken().trim();
                if (str.contains("-")){
                    StringTokenizer token = new StringTokenizer(str.trim(),"-");
                    final String tipus = token.nextToken().trim()+"-";
                    String num = token.nextToken().trim();
                    final Integer number = new Integer(num);
                    
                    Iterator iter = zone.getFeatures().iterator();
                    
                    while(iter.hasNext()){
                        Feature afeature = (Feature) iter.next();
                        if (afeature.getIdFet().getNumber().equals(number)){
                            feature=afeature;
                        }
                    }
                    
                    
                    if (feature==null){
                        ParameterCollector param = new ParameterCollector();
                        param.put("zone", zone);
                        param.put("site", site);
                        //Obtenir la categoria
                        
                        Category cat = getCategory(tipus);
                        param.put("type",cat);
                        
                        
                        try {
                            Feature.Inventory fi = new Feature.Inventory();
                            feature = fi.getNewObject(param);
                            //feature = (Feature) InventoryPool.getInventory("Feature").getNewObject(param);
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        
                        feature.getIdFet().setNumber(number);
                        zone.getFeatures().add(feature);
                        AbstractInventory.setObject(feature);
                        return feature;
                        
                    }
                    
                }
            }
        }
        
        if (feature==null && relfet.contains("-")){
            StringTokenizer token = new StringTokenizer(relfet.trim(),"-");
            final String tipus = token.nextToken().trim()+"-";
            String num = token.nextToken().trim();
            final Integer number = new Integer(num);
            
            Iterator iter = zone.getFeatures().iterator();
            
            while(iter.hasNext()){
                Feature afeature = (Feature) iter.next();
                if (afeature.getIdFet().getNumber().equals(number)){
                    feature=afeature;
                }
            }
            
            
            if (feature==null){
                ParameterCollector param = new ParameterCollector();
                param.put("zone", zone);
                param.put("site", site);
                //Obtenir la categoria
                
                
                Category cat = getCategory(tipus);
                param.put("type",cat);
                
                try {
                    Feature.Inventory fi = new Feature.Inventory();
                    feature = fi.getNewObject(param);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                feature.getIdFet().setNumber(number);
                zone.getFeatures().add(feature);
                AbstractInventory.setObject(site);
                
            }
        }
        //System.out.println(feature);
        return feature;
        
    }
    
    public TreeSet<Context> getContexts(String string){
        
        TreeSet <Context> set= new TreeSet <Context>();
        
        if (string.contains(",")||string.contains("/")||string.contains("=")){
            StringTokenizer token = null;
            if (string.contains(",")) token = new StringTokenizer(string, ",");
            if (string.contains("/")) token = new StringTokenizer(string, "/");
            if (string.contains("=")) token = new StringTokenizer(string, "=");
            while (token.hasMoreTokens()){
                String astring = token.nextToken().trim();
                Context context = getContext(astring, getZone(astring));
                if (context!=null)set.add(context);
            }
            
        }else{
            Context context = getContext(string.trim(), getZone(string));
            if (context!=null)set.add(context);
        }
        //System.out.println(set);
        return set;
        
    }
    
    public Context getContext(String string, final Zone zone) {
        
        Context context = null;
        
        final Integer number;
        try{
            number =	new Integer(string.subSequence(string.length()-3, string.length()).toString());
        }catch (Exception e) {
            return null;
        }
        
        Iterator iter = zone.getContexts().iterator();
        while (iter.hasNext()){
            Context acontext = (Context) iter.next();
            if (acontext.getId().getNumber().equals(number)){
                context = acontext;
                return context;
            }
        }
        
        
        //if (set.size()>0) return (Context) set.get(0);
        if (context==null){
//			Prepara els paramtres per la UE a crear
            ParameterCollector param = new ParameterCollector();
            param.put("type","Old");
            //Aconseguim la zona coresponent
            param.put("zone",zone);
            param.put("id",number);
            
            try {
                Context.Inventory ci = new Context.Inventory();
                context = (Context) ci.getNewObject(param);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return context;
        
    }
    
    
    public TreeSet<Sector> getSectors(String sect, Zone zone) {
        
        TreeSet<Sector> set= new TreeSet<Sector>();
        
        if (sect!=null & !sect.trim().equals("")){
            
            if (sect.contains(",")||sect.contains("/")){///En cas que hi hagi varis sectors
                StringTokenizer token =null;
                
                if (sect.contains(",")) token = new StringTokenizer(sect,",");
                if (sect.contains("/")) token = new StringTokenizer(sect,"/");
                
                while (token.hasMoreTokens()){
                    Sector sector = null;
                    String str = token.nextToken().trim();
                    //System.out.println(str);
                    Iterator iter = zone.getSectors().iterator();
                    while (iter.hasNext()){
                        Sector asector = (Sector) iter.next();
                        
                        if (asector.getIdSector().getNumber().equals(new Integer(str))){
                            sector=asector;
                            set.add(sector);
                        }
                        
                    }
                    
                    if (sector==null){//En cas que no existeixi tal sector en la zona
                        ParameterCollector param = new ParameterCollector();
                        param.put("zone", zone);
                        
                        try {
                            Sector.Inventory si = new Sector.Inventory();
                            sector = si.getNewObject(param);
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        
                        sector.getIdSector().setNumber(new Integer(str));
                        zone.getSectors().add(sector);
                        set.add(sector);
                        AbstractInventory.setObject(zone);
                    }
                    
                }
            }else{
                Sector sector = null;
                String str = sect.trim();
                //System.out.println(str);
                Iterator iter = zone.getSectors().iterator();
                while (iter.hasNext()){
                    Sector asector = (Sector) iter.next();
                    
                    if (asector!=null)if (asector.getIdSector().getNumber().equals(new Integer(str))){
                        sector=asector;
                        set.add(sector);
                    }
                }
                if (sector==null){//En cas que no existeixi tal sector en la zona
                    ParameterCollector param = new ParameterCollector();
                    param.put("zone", zone);
                    
                    try {
                        Sector.Inventory si = new Sector.Inventory();
                        sector = si.getNewObject(param);
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    sector.getIdSector().setNumber(new Integer(str));
                    zone.getSectors().add(sector);
                    set.add(sector);
                    AbstractInventory.setObject(zone);
                }
            }
        }
        
        return set;
    }
    
    
    
    public Zone getZone(String ue) {
        
        String nzone = (String) ue.trim().subSequence(0, ue.length()-3);
        final Integer integ = new Integer(nzone);
        Zone zone =null;
        
        //Set zoneset = site.getZones();
        List zonelist = Zone.Inventory.getList();
        int quant = zonelist.size();
        
        List zoneset = Zone.Inventory.getList(site);
        int quant2= zoneset.size();
        
        Iterator iter = zoneset.iterator();
        
        while (iter.hasNext()){
            Zone azone = (Zone) iter.next();
            if (azone.getIdZone().getNumber().equals(integ)){
                zone =azone;
                break;
            }
        }
        /*
        if (zone ==null){
         
            ParameterCollector param = new ParameterCollector();
            param.put("factoryid", "Zone");
            param.put("site",site);
         
            try {
                Zone.Inventory zi = new Zone.Inventory();
                zone = zi.getNewObject(param);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            zone.getIdZone().setNumber(integ);
         
         
        }
         
        AbstractInventory.setObject(zone);
        //System.out.println(zone);
         **/
        return zone;
    }
    
    
    static public void main(String args[]){
        new VilImport();
        System.exit(0);
    }
    
    private Action addAction(ParameterCollector param){
        if (this.site!=null){
            Action.Inventory ai = new Action.Inventory();
            
            try {
                Action action = ai.getNewObject(param);
                action.setId(Action.Inventory.getNewKey());
                action.setName((String)param.get("name"));
                action.setSite(this.site);
                action.setObjectives("");
                ai.setObject(action);
                
                return action;
            }catch (Exception e1) {
                LoggerProvider.getInstance().log(Level.WARNING,"Exception creating new Action",e1);
            }
        }
        return null;
    }
    
    private Action getAction(final String any) {
        
//Conecta a la base d'objectes standard
        ObjectContainer db = OCProvider.getInstance();
        //Obt? els assignments de la base
        List<Action> list = db.query(new Predicate<Action>(){
            public boolean match(Action action) {
                return action.getName().equals("Campanya "+any);
            }
        });
        if (list.size()!=0){// En cas que el assign estigui creat
            Action action = list.iterator().next();
            return action;
        } else {//En cas que no existeixi el assign s'en crea un
            ParameterCollector param = new ParameterCollector();
            param.put("name", "Campanya "+any);
            return addAction(param);
        }
    }
    
    private void newEquality(Context nou, Context contextNou) {
        List<Equality> list = Equality.Inventory.getEqualTo(nou);
        Equality equality;
        
        Iterator iter = list.iterator();
        
        while (iter.hasNext()){
            equality = (Equality) iter.next();
            if (equality.hasContext(nou) && equality.hasContext(contextNou)){
                return;
            }
        }

        Equality.Inventory ei = new Equality.Inventory();
        ParameterCollector param = new ParameterCollector();
        param.put("type","equality");
        param.put("contextA", nou);
        param.put("contextB", contextNou);
        
        equality = (Equality)ei.getNewObject(param);
        
        AbstractInventory.setObject(equality);
        System.out.println("New Equality "+nou.toString());
    }
    
    private void newAnterior(Context nou, Context contextNou) {
        List<Succesion> list = Succesion.Inventory.getPreviousTo(nou);
        Succesion succesion;
        
        Iterator iter = list.iterator();
        
        while (iter.hasNext()){
            succesion = (Succesion) iter.next();
            if (succesion.isPrevious(contextNou)){
                return;
            }
        }
        
        Succesion.Inventory ei = new Succesion.Inventory();
        ParameterCollector param = new ParameterCollector();
        param.put("type","succesion");
        param.put("contextA", nou);
        param.put("contextB", contextNou);
        
        succesion = (Succesion)ei.getNewObject(param);
        
        AbstractInventory.setObject(succesion);
        System.out.println("New Succesion "+nou.toString());
    }
    
    
}